package com.bojiu.lawsearch.lawsearch.service.impl;

import com.bojiu.lawsearch.lawsearch.mapper.*;
import com.bojiu.lawsearch.lawsearch.model.*;
import com.bojiu.lawsearch.lawsearch.service.TaskService;
import com.bojiu.lawsearch.lawsearch.util.*;
import com.bojiu.lawsearch.lawsearch.wxzf.WXZFService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.DelayQueue;

/**
 * @author: afdiao
 * @Date：2020/4/5 15:29
 * @Description:
 */
@Slf4j
@Service
public class TaskServiceImpl implements TaskService {

    @Autowired
    TaskMapper taskMapper;

    @Autowired
    UserAccountMapper userAccountMapper;

    @Autowired
    SettingMapper settingMapper;

    @Autowired
    LogMapper logMapper;

    @Autowired
    WXZFService wxzfService;

    @Autowired
    WxzfModelMapper wxzfModelMapper;

    @Autowired
    WxGoodsMapper wxGoodsMapper;

    @Autowired
    EngineerLabelMapper engineerLabelMapper;

    @Autowired
    EngineerMapper engineerMapper;

    @Autowired
    MailHandler mailHandler;

    @Autowired
    DelayQueue<OrderMessage> delayQueue;

    @Autowired
    LabelMapper labelMapper;

    @Autowired
    private WechatUserMapper wechatUserMapper;

    @Autowired
    private MsgUtil msgUtil;

    @Override
    public Page<Task> getTaskList(int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize, true);
        List<Task> list = taskMapper.getTaskList(new Task());
        list.forEach(task -> task.setEngineerList(engineerMapper.getUserfulEngineerBylabel(task.getLabelId())));
        PageInfo pageInfo = new PageInfo(list);
        Page page = new Page(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getPages(), pageInfo.getTotal(), list);
        return page;
    }

    @Transactional
    @Override
    public JsonResult publish(Task task, int userId, HttpServletRequest request) {
        //获取用户的余额以及积分信息
        UserAccount userAccount = (UserAccount) userAccountMapper.selectOneByExample(UtilTools.createExampleByKey("user_id", userId, UserAccount.class));
        if (userAccount == null) {
            userAccount = new UserAccount();
            userAccount.setUser_id(userId);
            userAccount.setAccount(0);
            userAccount.setIntegral(0);
            userAccountMapper.insertSelective(userAccount);
        }
        int account = userAccount.getAccount();
        userAccount.getIntegral();
        //获取系统设置的价格
        Setting setting = (Setting) settingMapper.selectOneByExample(UtilTools.createExampleByKey("key", Constances.QUESTION_PRICE, Setting.class));
        int questPrice = Integer.parseInt(setting.getValue());

        //判断扣除积分  先将积分转化成对应的金额
        Setting scoreUnit = (Setting) settingMapper.selectOneByExample(UtilTools.createExampleByKey("key", Constances.SCORE_TO_PRICE, Setting.class));
        Integer integral = userAccount.getIntegral();
        int scorePrice = (int) userAccount.getIntegral() / (int) (Integer.parseInt(scoreUnit.getValue()));
        //积分抵消的金额
        int scoreNum = 0;
        if (scorePrice > 0) {
            scoreNum = scorePrice >= questPrice ? questPrice : scorePrice;
        }
        //积分没有全部抵掉则计算余额抵消的金额  金额的单位都按照元算
        int accountNum = 0;
        if (account > 0) {
            if (scoreNum < questPrice) {
                int needprice = questPrice - scoreNum;
                accountNum = (account / 100) > needprice ? needprice : (account / 100);
            }
        }
        int needPay = 0;
        if ((scoreNum + accountNum) < questPrice) {
            needPay = questPrice - scoreNum - accountNum;
        }

        //更新扣除后的人员信息
        userAccount.setAccount(account - (accountNum * 100));
        userAccount.setIntegral(integral - scoreNum * Integer.parseInt(scoreUnit.getValue()));
        userAccountMapper.updateByExampleSelective(userAccount, UtilTools.createExampleByKey("user_id", userId, UserAccount.class));

        //添加历史变动记录
        if (scoreNum > 0) {
            Log scoreLog = new Log();
            scoreLog.setType(1);
            scoreLog.setUserId(userId);
            scoreLog.setBefore(String.valueOf(integral));
            scoreLog.setValue(String.valueOf(scoreNum * Integer.parseInt(scoreUnit.getValue())));
            scoreLog.setAfter(String.valueOf(integral - scoreNum * Integer.parseInt(scoreUnit.getValue())));
            scoreLog.setDetail(Constances.LOG_QUESTION_TYPE);
            logMapper.insertSelective(scoreLog);
        }
        if (accountNum > 0) {
            Log accountLog = new Log();
            accountLog.setType(2);
            accountLog.setUserId(userId);
            accountLog.setBefore(String.valueOf(account));
            accountLog.setValue(String.valueOf(accountNum * 100));
            accountLog.setAfter(String.valueOf(account - (accountNum * 100)));
            accountLog.setDetail(Constances.LOG_QUESTION_TYPE);
            logMapper.insertSelective(accountLog);
        }

        //添加任务数据库
        task.setPrice(needPay);
        task.setAccount(accountNum);
        task.setScore(scoreNum * Integer.parseInt(scoreUnit.getValue()));
        task.setUserId(userId);
        //设置任务状态
        if (needPay != 0) {
            //需要支付  返回支付二维码
            Gson gson = new Gson();
            task.setStatus(3);
            //创建支付订单获取支付二维码
            JsonResult jsonResult = wxzfService.nativeOrder(needPay * 100, Constances.QUESTION_BODY, request);
            if (!"200".equals(jsonResult.getCode())) {
                log.error("微信支付创建订单失败");
                return new JsonResult(ResultCode.FAIL);
            }
            Object data = jsonResult.getData();
            JsonObject jsonObject = gson.fromJson(gson.toJson(data), JsonObject.class);
            String orderNum = jsonObject.get("orderNum").getAsString();
            task.setOrderNum(orderNum);
            //订单号关联模块
            Wxzf_model wxzf_model = new Wxzf_model();
            wxzf_model.setOrderNum(orderNum);
            wxzf_model.setModel("question");
            wxzf_model.setPrice(needPay * 100);
            wxzfModelMapper.insertSelective(wxzf_model);
            //获取支付二维码返回
            String code = jsonObject.get("code").getAsString();
            taskMapper.insertSelective(task);
            int taskId = taskMapper.getMaxId();
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("payCode", code);
            resultMap.put("taskId", taskId);
//            JsonObject resultJson = new JsonObject();
//            resultJson.addProperty("payCode", code);
//            resultJson.addProperty("taskId", String.valueOf(taskId));
            return new JsonResult(ResultCode.PAY, resultMap);

        } else {
            //无需支付表示已经用积分或者余额完成抵扣，立即发布该任务
            //先默认状态是0 ，然后根据具体发布流程再修改
            task.setStatus(0);
            taskMapper.insertSelective(task);
            int taskId = taskMapper.getMaxId();
            publishByStatus(taskId);
            return new JsonResult(ResultCode.SUCCESS);
        }
    }

    @Override
    public JsonResult checkPay(int taskId, int userId) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", taskId);
        map.put("userId", userId);
        Task task = (Task) taskMapper.selectOneByExample(UtilTools.createExampleByMap(map, Task.class));
        if (task.getStatus() == 3) {
            log.error("该任务尚未支付");
            return new JsonResult(ResultCode.PAY);
        }
        return new JsonResult(ResultCode.SUCCESS);
    }

    /**
     * 根据系统设置状态执行自动或者手动发布任务
     *
     * @param taskId
     */
    @Override
    public void publishByStatus(int taskId) {
        //获取系统设置  1自动匹配  2管理员手动匹配
        Setting setting = (Setting) settingMapper.selectOneByExample(UtilTools.createExampleByKey("key", Constances.AUTO_PUBLISH, Setting.class));
        Task task = (Task) taskMapper.selectOneByExample(UtilTools.createExampleByKey("id", taskId, Task.class));
        if (2 == Integer.parseInt(setting.getValue())) {
            task.setStatus(2);
            taskMapper.updateByExampleSelective(task, UtilTools.createExampleByKey("id", taskId, Task.class));
        } else {
            //系统自动匹配
            Integer labelId = task.getLabelId();

            //根据任务标签关联工程师
//            List<Engineer> engineers = engineerMapper.getUserfulEngineerBylabel(labelId);
//            for (Engineer engineer : engineers) {
//                //TODO:
////                mailHandler.sendMail("有你擅长的问题等待回，快来抢单！！！", engineer.getMail());
//            }
            task.setStatus(1);
            taskMapper.updateByExampleSelective(task, UtilTools.createExampleByKey("id", taskId, Task.class));
        }

        //将任务放到内存等待倒计时
        OrderMessage orderMessage = new OrderMessage();
        orderMessage.setUserId(task.getUserId());
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        orderMessage.setUUID(uuid);
        orderMessage.setType("publish");
        orderMessage.setEngineerId(null);
        orderMessage.setQuestionId(taskId);
        //设置持续时间
        orderMessage.setTime(5 * 24 * 3600);
        delayQueue.offer(orderMessage);
    }

    @Override
    public JsonResult memberPay(int goodsId, HttpServletRequest request, int userId) {
        Gson gson = new Gson();
        WxGoods wxGoods = (WxGoods) wxGoodsMapper.selectOneByExample(UtilTools.createExampleByKey("id", goodsId, WxGoods.class));
        int price = wxGoods.getPrice();
        //创建支付订单获取支付二维码
        JsonResult jsonResult = wxzfService.nativeOrder(price, Constances.QUESTION_BODY, request);
        if (!"200".equals(jsonResult.getCode())) {
            log.error("微信支付创建订单失败");
            return new JsonResult(ResultCode.FAIL);
        }
        //
        //订单号关联模块
        Object data = jsonResult.getData();
        JsonObject jsonObject = gson.fromJson(gson.toJson(data), JsonObject.class);
        String orderNum = jsonObject.get("orderNum").getAsString();
        Wxzf_model wxzf_model = new Wxzf_model();
        wxzf_model.setOrderNum(orderNum);
        wxzf_model.setModel("member");
        wxzf_model.setPrice(price);
        wxzf_model.setGoodsId(goodsId);
        wxzf_model.setHandle(0);
        wxzf_model.setUserId(userId);
        wxzfModelMapper.insertSelective(wxzf_model);
        String code = jsonObject.get("code").getAsString();
        return new JsonResult(ResultCode.SUCCESS, code);
    }

    @Override
    public Page<Task> getTask(int userId, int pageSize, int pageNum) {
        Engineer engineer = (Engineer) engineerMapper.selectOneByExample(UtilTools.createExampleByKey("user_id", userId, Engineer.class));
        List<EngineerLabel> engineerLabels = engineerLabelMapper.selectByExample(UtilTools.createExampleByKey("userId", engineer.getUser_id(), EngineerLabel.class));
        //获取该工程师所有的链接
        Set<Integer> labelIds = new HashSet<>();
        for (EngineerLabel engineerLabel : engineerLabels) {
            labelIds.add(engineerLabel.getLabelId());
        }
        PageHelper.startPage(pageNum, pageSize, true);
        String changeSetForSql = UtilTools.changeSetForSql(labelIds);
        //根据标签关联任务
        List<Task> taskByLabels = taskMapper.getTaskByLabels(changeSetForSql);
        PageInfo pageInfo = new PageInfo(taskByLabels);
        Page page = new Page(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getPages(), pageInfo.getTotal(), taskByLabels);
        return page;
    }

    @Override
    public Page<Task> getEngineerMyTask(int userId, int pageSize, int pageNum) {
        Map<String, Object> map = new HashMap<>();
        map.put("user_id", userId);
        map.put("is_authentication", 1);
        Engineer engineer = (Engineer) engineerMapper.selectOneByExample(UtilTools.createExampleByMap(map, Engineer.class));
        Task task = new Task();
        task.setEngineerId(engineer.getId());
        PageHelper.startPage(pageNum, pageSize, true);
//        List<Task> taskList = taskMapper.getTaskList(task);
        List<Task> taskList = taskMapper.selectByExample(UtilTools.createExampleByKey("engineerId", engineer.getId(), Task.class));
        for (Task ta : taskList) {
            WechatUser engineerUser = (WechatUser) wechatUserMapper.selectOneByExample(UtilTools.createExampleByKey("id", engineer.getUser_id(), WechatUser.class));
            engineerUser.setEngineer(engineer);
            ta.setEngineerName(engineer.getName());
            ta.setEngineerUser(engineerUser);

            WechatUser wechatUser = (WechatUser) wechatUserMapper.selectOneByExample(UtilTools.createExampleByKey("id", ta.getUserId(), WechatUser.class));
            ta.setWechatUser(wechatUser);
        }
        PageInfo pageInfo = new PageInfo(taskList);
        Page page = new Page(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getPages(), pageInfo.getTotal(), taskList);
        return page;
    }

    @Override
    public Page<Task> geMyTask(int userId, int pageSize, int pageNum) {
        Task task = new Task();
        task.setUserId(userId);
        PageHelper.startPage(pageNum, pageSize, true);
        List<Task> taskList = taskMapper.getTaskList(task);
        taskList.forEach(t -> {
            if (t.getEngineerId() != null) {
                Engineer engineer = (Engineer) engineerMapper.selectOneByExample(UtilTools.createExampleByKey("id",t.getEngineerId(), Engineer.class));
                WechatUser engineerUser = (WechatUser) wechatUserMapper.selectOneByExample(UtilTools.createExampleByKey("id", engineer.getUser_id(), WechatUser.class));
                t.setEngineerName(engineer.getName());
                t.setEngineerUser(engineerUser);
            }
        });
        PageInfo pageInfo = new PageInfo(taskList);
        Page page = new Page(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getPages(), pageInfo.getTotal(), taskList);
        return page;
    }

    @Override
    public synchronized JsonResult orderTask(int userId, int taskId) {
        Task task = (Task) taskMapper.selectOneByExample(UtilTools.createExampleByKey("id", taskId, Task.class));
        if (task.getStatus() != 1) {
            log.debug("该任务不能抢单，state is:{}", task.getStatus());
            return new JsonResult(ResultCode.LATE_OREDER);
        }
        task.setStatus(4);
        task.setEngineerId(userId);
        taskMapper.updateByExampleSelective(task, UtilTools.createExampleByKey("id", taskId, Task.class));
        return new JsonResult(ResultCode.SUCCESS);
    }

    @Override
    public JsonResult fee(int fee, int userId, HttpServletRequest request) {
        Gson gson = new Gson();
        fee = fee * 100;
        //创建支付订单获取支付二维码
        JsonResult jsonResult = wxzfService.nativeOrder(fee, Constances.FEE_BODY, request);
        if (!"200".equals(jsonResult.getCode())) {
            log.error("微信支付创建订单失败");
            return new JsonResult(ResultCode.FAIL);
        }
        //
        //订单号关联模块
        Object data = jsonResult.getData();
        JsonObject jsonObject = gson.fromJson(gson.toJson(data), JsonObject.class);
        String orderNum = jsonObject.get("orderNum").getAsString();
        Wxzf_model wxzf_model = new Wxzf_model();
        wxzf_model.setOrderNum(orderNum);
        wxzf_model.setModel("fee");
        wxzf_model.setPrice(fee);
        wxzf_model.setHandle(0);
        wxzf_model.setUserId(userId);
        wxzfModelMapper.insertSelective(wxzf_model);
        String code = jsonObject.get("code").getAsString();
        return new JsonResult(ResultCode.SUCCESS, code);
    }

    @Override
    public JsonResult handleTask(int taskId, int userId, String answer) {
        Task task = new Task();
        task.setAnswer(answer);
        task.setStatus(5);
        taskMapper.updateByExampleSelective(task, UtilTools.createExampleByKey("id", taskId, Task.class));
        Task userTask = (Task) taskMapper.selectOneByExample(UtilTools.createExampleByKey("id", taskId, Task.class));
        WechatUser user = (WechatUser) wechatUserMapper.selectOneByExample(UtilTools.createExampleByKey("id", userTask.getUserId(), WechatUser.class));
        msgUtil.sendMsgToUserForHandle(user.getAccount());
        //开始倒计时
        OrderMessage orderMessage = new OrderMessage();
        orderMessage.setQuestionId(taskId);
        orderMessage.setType("handle");
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        orderMessage.setUUID(uuid);
        //设置持续时间
        orderMessage.setTime(5 * 24 * 3600);
        delayQueue.offer(orderMessage);
        return new JsonResult(ResultCode.SUCCESS);
    }

    @Override
    public JsonResult getBackList(int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize, true);
        List<Task> list = taskMapper.selectAll();
        //处理问题的标签中文名
        for (Task task : list) {
            Label label = (Label) labelMapper.selectOneByExample(UtilTools.createExampleByKey("id", task.getLabelId(), Label.class));
            task.setLabelName(label.getName());
            Integer engineerId = task.getEngineerId();
            if (engineerId != null || engineerId != 0) {

            }
        }
        return null;
    }

    @Override
    public JsonResult deploy(int taskId, int engineerId) {
        Task task = new Task();
        task.setEngineerId(engineerId);
        task.setStatus(4);
        taskMapper.updateByExampleSelective(task, UtilTools.createExampleByKey("id", taskId, Task.class));
        Engineer engineer = (Engineer) engineerMapper.selectOneByExample(UtilTools.createExampleByKey("id", engineerId, Engineer.class));
        WechatUser engineerUser = (WechatUser) wechatUserMapper.selectOneByExample(UtilTools.createExampleByKey("id", engineer.getUser_id(), WechatUser.class));
        Task userTask = (Task) taskMapper.selectOneByExample(UtilTools.createExampleByKey("id", taskId, Task.class));
        WechatUser user = (WechatUser) wechatUserMapper.selectOneByExample(UtilTools.createExampleByKey("id", userTask.getUserId(), WechatUser.class));
        //发送短信
        msgUtil.sendMsgToUser(user.getAccount());
        msgUtil.sendMsgToEngineer(engineerUser.getAccount());
        return new JsonResult(ResultCode.SUCCESS);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult marking(Task task, BigDecimal star) {
        // 给工程师打分，评价等于完成
        Task taskParams = new Task();
//        BeanUtils.copyProperties(task, taskParams);
        taskParams.setStatus(6);
        taskParams.setStar(star);
        taskMapper.updateByExampleSelective(taskParams, UtilTools.createExampleByKey("id", task.getId(), Task.class));
        // 计算积分
        Setting scoreToPriceSetting = (Setting) settingMapper.selectOneByExample(UtilTools.createExampleByKey("key", Constances.SCORE_TO_PRICE, Setting.class));
        int score = (task.getPrice() + task.getAccount()) * Integer.parseInt(scoreToPriceSetting.getValue()) + task.getScore();
        // 工程师分成
        UserAccount userAccount = new UserAccount();
        Setting answerQuestionProportionSetting = (Setting) settingMapper.selectOneByExample(UtilTools.createExampleByKey("key", Constances.ANSWER_QUESTION_PROPORTION, Setting.class));
        userAccount.setIntegral(new BigDecimal(score).multiply(new BigDecimal(answerQuestionProportionSetting.getValue())).intValue());
        Engineer engineer = (Engineer) engineerMapper.selectOneByExample(UtilTools.createExampleByKey("id", task.getEngineerId(), Engineer.class));
        userAccountMapper.updateByExampleSelective(userAccount, UtilTools.createExampleByKey("user_id", engineer.getUser_id(), UserAccount.class));
        // 上家分成
        WechatUser wechatUser = (WechatUser) wechatUserMapper.selectOneByExample(UtilTools.createExampleByKey("id", task.getUserId(), WechatUser.class));
        if (!StringUtils.isEmpty(wechatUser.getExtend())) {
            WechatUser engineerUser = (WechatUser) wechatUserMapper.selectOneByExample(UtilTools.createExampleByKey("id", wechatUser.getExtend(), WechatUser.class));
            if (engineerUser.getType().equals(0)) {
                // 普通用户
                Setting userProportionSetting = (Setting) settingMapper.selectOneByExample(UtilTools.createExampleByKey("key", Constances.USER_PROPORTION, Setting.class));
                userAccount.setIntegral(new BigDecimal(score).multiply(new BigDecimal(userProportionSetting.getValue())).intValue());
                userAccountMapper.updateByExampleSelective(userAccount, UtilTools.createExampleByKey("user_id", wechatUser.getExtend(), UserAccount.class));
            } else if (engineerUser.getType().equals(1)) {
                // 工程师
                Setting engineerProportionSetting = (Setting) settingMapper.selectOneByExample(UtilTools.createExampleByKey("key", Constances.ENGINEER_PROPORTION, Setting.class));
                userAccount.setIntegral(new BigDecimal(score).multiply(new BigDecimal(engineerProportionSetting.getValue())).intValue());
                userAccountMapper.updateByExampleSelective(userAccount, UtilTools.createExampleByKey("user_id", wechatUser.getExtend(), UserAccount.class));
            }
        }

        return new JsonResult(ResultCode.SUCCESS);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult changeEngineer(Task task) {
        task.setStatus(2);
        task.setEngineerId(null);
        taskMapper.updateByExample(task, UtilTools.createExampleByKey("id", task.getId(), Task.class));
        return new JsonResult(ResultCode.SUCCESS);
    }

    @Override
    public List<Task> queryList(Task task) {
        return taskMapper.getTaskList(task);
    }

    @Override
    public Task queryById(int taskId) {
        return (Task) taskMapper.selectOneByExample(UtilTools.createExampleByKey("id", taskId, Task.class));
    }
}
